1 /*
2 * Written by Doug Lea and Martin Buchholz with assistance from
3 * members of JCP JSR-166 Expert Group and released to the public
4 * domain, as explained at
5 * http://creativecommons.org/publicdomain/zero/1.0/
6 */
7
8 /*
9 * Source:
10 * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/extra/AtomicDouble.java?revision=1.13
11 * (Modified to adapt to guava coding conventions and
12 * to use AtomicLongFieldUpdater instead of sun.misc.Unsafe)
13 */
14
15 package com.google.common.util.concurrent;
16
17 import static java.lang.Double.doubleToRawLongBits;
18 import static java.lang.Double.longBitsToDouble;
19
20 import java.util.concurrent.atomic.AtomicLongFieldUpdater;
21
22 /**
23 * A {@code double} value that may be updated atomically. See the
24 * {@link java.util.concurrent.atomic} package specification for
25 * description of the properties of atomic variables. An {@code
26 * AtomicDouble} is used in applications such as atomic accumulation,
27 * and cannot be used as a replacement for a {@link Double}. However,
28 * this class does extend {@code Number} to allow uniform access by
29 * tools and utilities that deal with numerically-based classes.
30 *
31 * <p><a name="bitEquals">This class compares primitive {@code double}
32 * values in methods such as {@link #compareAndSet} by comparing their
33 * bitwise representation using {@link Double#doubleToRawLongBits},
34 * which differs from both the primitive double {@code ==} operator
35 * and from {@link Double#equals}, as if implemented by:
36 * <pre> {@code
37 * static boolean bitEquals(double x, double y) {
38 * long xBits = Double.doubleToRawLongBits(x);
39 * long yBits = Double.doubleToRawLongBits(y);
40 * return xBits == yBits;
41 * }}</pre>
42 *
43 * <p>It is possible to write a more scalable updater, at the cost of
44 * giving up strict atomicity. See for example
45 * <a href="http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166edocs/jsr166e/DoubleAdder.html">
46 * DoubleAdder</a>
47 * and
48 * <a href="http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166edocs/jsr166e/DoubleMaxUpdater.html">
49 * DoubleMaxUpdater</a>.
50 *
51 * @author Doug Lea
52 * @author Martin Buchholz
53 * @since 11.0
54 */
55 public class AtomicDouble extends Number implements java.io.Serializable {
56 private static final long serialVersionUID = 0L;
57
58 private transient volatile long value;
59
60 private static final AtomicLongFieldUpdater<AtomicDouble> updater =
61 AtomicLongFieldUpdater.newUpdater(AtomicDouble.class, "value");
62
63 /**
64 * Creates a new {@code AtomicDouble} with the given initial value.
65 *
66 * @param initialValue the initial value
67 */
68 public AtomicDouble(double initialValue) {
69 value = doubleToRawLongBits(initialValue);
70 }
71
72 /**
73 * Creates a new {@code AtomicDouble} with initial value {@code 0.0}.
74 */
75 public AtomicDouble() {
76 // assert doubleToRawLongBits(0.0) == 0L;
77 }
78
79 /**
80 * Gets the current value.
81 *
82 * @return the current value
83 */
84 public final double get() {
85 return longBitsToDouble(value);
86 }
87
88 /**
89 * Sets to the given value.
90 *
91 * @param newValue the new value
92 */
93 public final void set(double newValue) {
94 long next = doubleToRawLongBits(newValue);
95 value = next;
96 }
97
98 /**
99 * Eventually sets to the given value.
100 *
101 * @param newValue the new value
102 */
103 public final void lazySet(double newValue) {
104 set(newValue);
105 // TODO(user): replace with code below when jdk5 support is dropped.
106 // long next = doubleToRawLongBits(newValue);
107 // updater.lazySet(this, next);
108 }
109
110 /**
111 * Atomically sets to the given value and returns the old value.
112 *
113 * @param newValue the new value
114 * @return the previous value
115 */
116 public final double getAndSet(double newValue) {
117 long next = doubleToRawLongBits(newValue);
118 return longBitsToDouble(updater.getAndSet(this, next));
119 }
120
121 /**
122 * Atomically sets the value to the given updated value
123 * if the current value is <a href="#bitEquals">bitwise equal</a>
124 * to the expected value.
125 *
126 * @param expect the expected value
127 * @param update the new value
128 * @return {@code true} if successful. False return indicates that
129 * the actual value was not bitwise equal to the expected value.
130 */
131 public final boolean compareAndSet(double expect, double update) {
132 return updater.compareAndSet(this,
133 doubleToRawLongBits(expect),
134 doubleToRawLongBits(update));
135 }
136
137 /**
138 * Atomically sets the value to the given updated value
139 * if the current value is <a href="#bitEquals">bitwise equal</a>
140 * to the expected value.
141 *
142 * <p>May <a
143 * href="http://download.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html#Spurious">
144 * fail spuriously</a>
145 * and does not provide ordering guarantees, so is only rarely an
146 * appropriate alternative to {@code compareAndSet}.
147 *
148 * @param expect the expected value
149 * @param update the new value
150 * @return {@code true} if successful
151 */
152 public final boolean weakCompareAndSet(double expect, double update) {
153 return updater.weakCompareAndSet(this,
154 doubleToRawLongBits(expect),
155 doubleToRawLongBits(update));
156 }
157
158 /**
159 * Atomically adds the given value to the current value.
160 *
161 * @param delta the value to add
162 * @return the previous value
163 */
164 public final double getAndAdd(double delta) {
165 while (true) {
166 long current = value;
167 double currentVal = longBitsToDouble(current);
168 double nextVal = currentVal + delta;
169 long next = doubleToRawLongBits(nextVal);
170 if (updater.compareAndSet(this, current, next)) {
171 return currentVal;
172 }
173 }
174 }
175
176 /**
177 * Atomically adds the given value to the current value.
178 *
179 * @param delta the value to add
180 * @return the updated value
181 */
182 public final double addAndGet(double delta) {
183 while (true) {
184 long current = value;
185 double currentVal = longBitsToDouble(current);
186 double nextVal = currentVal + delta;
187 long next = doubleToRawLongBits(nextVal);
188 if (updater.compareAndSet(this, current, next)) {
189 return nextVal;
190 }
191 }
192 }
193
194 /**
195 * Returns the String representation of the current value.
196 * @return the String representation of the current value
197 */
198 public String toString() {
199 return Double.toString(get());
200 }
201
202 /**
203 * Returns the value of this {@code AtomicDouble} as an {@code int}
204 * after a narrowing primitive conversion.
205 */
206 public int intValue() {
207 return (int) get();
208 }
209
210 /**
211 * Returns the value of this {@code AtomicDouble} as a {@code long}
212 * after a narrowing primitive conversion.
213 */
214 public long longValue() {
215 return (long) get();
216 }
217
218 /**
219 * Returns the value of this {@code AtomicDouble} as a {@code float}
220 * after a narrowing primitive conversion.
221 */
222 public float floatValue() {
223 return (float) get();
224 }
225
226 /**
227 * Returns the value of this {@code AtomicDouble} as a {@code double}.
228 */
229 public double doubleValue() {
230 return get();
231 }
232
233 /**
234 * Saves the state to a stream (that is, serializes it).
235 *
236 * @serialData The current value is emitted (a {@code double}).
237 */
238 private void writeObject(java.io.ObjectOutputStream s)
239 throws java.io.IOException {
240 s.defaultWriteObject();
241
242 s.writeDouble(get());
243 }
244
245 /**
246 * Reconstitutes the instance from a stream (that is, deserializes it).
247 */
248 private void readObject(java.io.ObjectInputStream s)
249 throws java.io.IOException, ClassNotFoundException {
250 s.defaultReadObject();
251
252 set(s.readDouble());
253 }
254 }